package org.springblade.auth.granter;

import lombok.extern.slf4j.Slf4j;
import org.springblade.common.constant.SecurityConstants;
import org.springblade.common.security.service.CsjUser;
import org.springblade.common.security.util.UserDetailUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.system.user.entity.UserInfo;
import org.springblade.system.user.feign.IUserClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;

import java.util.*;

/**
 * 自定义手机app手机微信QQ登陆
 */
@Slf4j
public class WeChatLoginTokenGranter extends AbstractTokenGranter {
	private static final String GRANT_TYPE = "social";
	//租户ID
	private static final String TENANT_ID ="000001";
	private IUserClient userClient;
	private CacheManager cacheManager;
	public WeChatLoginTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory,IUserClient userClient,CacheManager cacheManager) {
		super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
		this.userClient = userClient;
		this.cacheManager = cacheManager;
	}
	@Override
	protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
		Map<String, String> parameters = new LinkedHashMap(tokenRequest.getRequestParameters());
		//获取验证参数
		String userPhone = Func.toStr(parameters.get("username"));
		String providerId = Func.toStr(parameters.get("providerId"));
		String providerType = Func.toStr(parameters.get("providerType"));
		//验证提交参数是否为空
		if(Func.isEmpty(userPhone) || Func.isEmpty(providerType)){
			throw new InvalidGrantException("账号或验证码不正确");
		}
		//都不为空进行获取用户信息
		//从缓存中获取
		Cache cache = cacheManager.getCache("user_details");
		String cacheKey = Func.join(new String[]{TENANT_ID,userPhone,providerType,providerId},"_");
		UserDetails user;
		//缓存中取到用户信息
		if (cache != null && cache.get(cacheKey) != null) {
			user = (CsjUser) cache.get(cacheKey).get();
		}else {
			//缓存中没有取到，从数据库查
			user = UserDetailUtil.getUserDetails(userClient.userInfo(TENANT_ID,userPhone,providerType,providerId));
		}
		Authentication userAuth = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
		((AbstractAuthenticationToken) userAuth).setDetails(parameters);
		OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
		return  new OAuth2Authentication(storedOAuth2Request, userAuth);
	}
}
